package com.xiao.singleapp.common.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;

import java.math.BigDecimal;
import java.util.regex.Pattern;

/**
 * 字符串操作工具类
 */
public class StringUtil {

    /**
     * 判断字符串0
     */
    public static final String ZERO_STR = "0";
    /**
     * 判断字符串1
     */
    public static final String ONE_STR = "1";
    /**
     * 判断字符串2
     */
    public static final String TWO_STR = "2";
    /**
     * 判断字符串3
     */
    public static final String COMMA = ",";
    public static final String EMPTY = "";
    public static final String UNDERLINE = "_";
    public static final String THREE_STR = "3";
    public static final char C_SEMICOLON = ';';
    public static final String C_QUESTION_CH = "？";
    public static final String C_QUESTION_EN = "?";
    // 下划线
    private static final char SEPARATOR = '_';
    // 非中文、英文，既特殊符号
    private static final String SPECIAL_CHAR = "[^a-zA-Z0-9\\u4E00-\\u9FA5]";
    private static final char UNDERLINE_CHAR = '_';
    public static final String MINUTE = "分";
    public static final String ZERO_UP = "零";
    // 过滤特殊字符
    public static Pattern SPECIAL_STR = Pattern.compile("[\\？#*\\?]");

    /**
     * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空，则返回空字符串。</br>
     * 例如：HelloWorld->HELLO_WORLD
     *
     * @param name 转换前的驼峰式命名的字符串
     * @return 转换后下划线大写方式命名的字符串
     */
    public static String underscoreName(String name) {
        StringBuilder result = new StringBuilder();
        if (name != null && name.length() > 0) {
            // 将第一个字符处理成大写
            result.append(name.substring(0, 1).toUpperCase());
            // 循环处理其余字符
            for (int i = 1; i < name.length(); i++) {
                String s = name.substring(i, i + 1);
                // 在大写字母前添加下划线
                if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) {
                    result.append("_");
                }
                // 其他字符直接转成大写
                result.append(s.toUpperCase());
            }
        }
        return result.toString();
    }

    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。</br>
     * 例如：HELLO_WORLD->HelloWorld
     *
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String camelName(String name) {
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (name == null || name.isEmpty()) {
            // 没必要转换
            return EMPTY;
        } else if (!name.contains(UNDERLINE)) {
            // 不含下划线，仅将首字母小写
            return name.substring(0, 1).toLowerCase() + name.substring(1);
        }
        // 用下划线将原始字符串分割
        String[] camels = name.split(UNDERLINE);
        for (String camel : camels) {
            // 跳过原始字符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty()) {
                continue;
            }
            // 处理真正的驼峰片段
            if (result.length() == 0) {
                // 第一个驼峰片段，全部字母都小写
                result.append(camel.toLowerCase());
            } else {
                // 其他的驼峰片段，首字母大写
                result.append(camel.substring(0, 1).toUpperCase());
                result.append(camel.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

    /**
     * 获取字符串倒数第N次出现的位置，并截取
     */
    public static String subStringByLastIndexOf(String sourceStr, String targetStr, int num) {
        String returnStr = sourceStr;
        for (int i = 0; i < num; i++) {
            returnStr = returnStr.substring(0, returnStr.lastIndexOf(targetStr));
        }
        return returnStr;
    }

    /**
     * 获取字符串出现的次数
     */
    public static int getStringCount(String source, String targetStr) {
        return (source.length() - source.replace(targetStr, EMPTY).length()) / targetStr.length();
    }

    /**
     * 判断一个对象是否为空
     */
    public static boolean isNull(Object object) {
        return object == null;
    }

    /**
     * 判断一个对象是否非空
     */
    public static boolean isNotNull(Object object) {
        return !isNull(object);
    }

    public static String valueOf(Object obj) {
        return (obj == null) ? EMPTY : obj.toString();
    }

    /**
     * 判断一个字符串是否包含有效字符
     */
    public static boolean isEmptyNotTrim(String str) {
        return str == null || str.length() == 0 || StringUtils.trim(str).length() == 0
                || "&nbsp;".equals(str.trim());
    }

    /**
     * 下划线转驼峰命名
     */
    public static String toUnderScoreCase(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 前置字符是否大写
        boolean preCharIsUpperCase;
        // 当前字符是否大写
        boolean curreCharIsUpperCase;
        // 下一字符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (i > 0) {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            } else {
                preCharIsUpperCase = false;
            }

            curreCharIsUpperCase = Character.isUpperCase(c);

            if (i < (str.length() - 1)) {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }

            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
                sb.append(SEPARATOR);
            } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
                sb.append(SEPARATOR);
            }
            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }

    /**
     * 比较字符串是否相等
     */
    public static Boolean equals(String str, String str1) {
        if (str == null) {
            str = EMPTY;
        }
        if (str1 == null) {
            str1 = EMPTY;
        }
        return str.equals(str1);
    }

    /**
     * 如果第一个字符为空，返回第二个字符
     */
    public static String nvl(Object str1, Object str2) {
        if (isEmptyNotTrim(valueOf(str1))) {
            return valueOf(str2);
        }
        return valueOf(str1);
    }

    public static String leftPad(String str, int size, String padStr) {
        int num = 8192;
        if (str == null) {
            return null;
        } else {
            if (isEmpty(padStr)) {
                padStr = " ";
            }

            int padLen = padStr.length();
            int strLen = str.length();
            int pads = size - strLen;
            if (pads <= 0) {
                return str;
            } else if (padLen == 1 && pads <= num) {
                return leftPad(str, size, String.valueOf(padStr.charAt(0)));
            } else if (pads == padLen) {
                return padStr.concat(str);
            } else if (pads < padLen) {
                return padStr.substring(0, pads).concat(str);
            } else {
                char[] padding = new char[pads];
                char[] padChars = padStr.toCharArray();

                for (int i = 0; i < pads; ++i) {
                    padding[i] = padChars[i % padLen];
                }

                return (new String(padding)).concat(str);
            }
        }
    }

    /**
     * 去除特殊字符，只保留英文，数字和汉字
     */
    public static String specialChar(String str) {
        if (str == null) {
            return EMPTY;
        }
        return str.replaceAll(SPECIAL_CHAR, EMPTY);
    }

    /**
     * 将char直接转化为int，其值就是字符的ascii
     */
    public static int charToByteAscii2(char ch) {
        return ch;
    }

    /**
     * ascii转换为char 直接int强制转换为char
     */
    public static char byteAsciiToChar(int ascii) {
        return (char) ascii;
    }

    /**
     * 获取XML转义之后的值
     */
    public static String getXmlValue(Object object) {
        String str = valueOf(object);
        return str.replace("<", "&lt;").
                replace(">", "&gt;").
                replace("&", "&amp;").
                replace("'", "&apos;").
                replace("\"", "&quot;").
                replace(" ", "&nbsp;");
    }

    /**
     * 列名转换成Java属性名
     * 下划线后第一个字符大写，而后去除下划线
     */
    public static String columnToJava(String columnName) {
        return WordUtils.capitalizeFully(columnName, '_').replace("_", "");
    }

    /**
     * 下划线 转 驼峰
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = Character.toLowerCase(param.charAt(i));
            if (c == UNDERLINE_CHAR) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }


    /**
     * 转大写
     *
     * @param str
     * @return
     */
    public static String upperCase(String str) {
        str = valueOf(str);
        return str.toUpperCase();
    }

    /**
     * 判断监管条件
     *
     * @param controlMa         海关监管条件
     * @param controlInspection 商品监管条件
     * @return 海关监管条件为 "A" 且 商品监管条件为 "M" 返回TRUE；
     * 商品监管条件为 "L" 返回TRUE
     */
    public static boolean getIsInspection(String controlMa, String controlInspection) {
        if (controlMa == null) {
            controlMa = "";
        }
        if (controlInspection == null) {
            controlInspection = "";
        }
        boolean condition1 = controlMa.contains("A") && controlInspection.contains("M");
        boolean condition2 = controlInspection.contains("L");

        return condition1 || condition2;
    }

    @SuppressWarnings("unchecked")
    public static  <T> T cast(Object obj) {
        return (T) obj;
    }

    //金额转中文大写
    public static String amountToDx(BigDecimal bigDecimal) {
        String UNIT = "万千佰拾亿千佰拾万千佰拾元角分";
        String DIGIT = "零壹贰叁肆伍陆柒捌玖";
        double MAX_VALUE = 9999999999999.99D;
        double v = bigDecimal.doubleValue();

        if (v < 0 || v > MAX_VALUE) {
            return "参数非法!";
        }
        long l = Math.round(v * 100);
        if (l == 0) {
            return "零元整";
        }
        String strValue = l + "";
        // i用来控制数
        int i = 0;
        // j用来控制单位
        int j = UNIT.length() - strValue.length();
        String rs = "";
        boolean isZero = false;
        for (; i < strValue.length(); i++, j++) {
            char ch = strValue.charAt(i);
            if (ch == '0') {
                isZero = true;
                if (UNIT.charAt(j) == '亿' || UNIT.charAt(j) == '万' || UNIT.charAt(j) == '元') {
                    rs = rs + UNIT.charAt(j);
                    isZero = false;
                }
            } else {
                if (isZero) {
                    rs = rs + ZERO_UP;
                    isZero = false;
                }
                rs = rs + DIGIT.charAt(ch - '0') + UNIT.charAt(j);
            }
        }
        if (!rs.endsWith(MINUTE)) {
            rs = rs + "整";
        }
        rs = rs.replaceAll("亿万", "亿");
        return rs;
    }


    /**
     * 字符串是否为空，空的定义如下:<br>
     * 1、为null <br>
     * 2、为""<br>
     *
     * @param str 被检测的字符串
     * @return 是否为空
     */
    public static boolean isEmpty(CharSequence str) {
        return str == null || str.length() == 0;
    }

    /**
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
}
